using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Threading;

namespace cb0tServer
{
    class UrbanDictionary
    {
        private Thread thread;
        private bool busy = false;

        private ushort vroom = 0;
        private String query = String.Empty;

        public void Query(ushort vroom, String query)
        {
            if (busy)
            {
                UserPool.Broadcast(vroom, ServerOutboundPackets.AnnoucePacket("wait a few seconds and then try again"));
                return;
            }

            this.vroom = vroom;
            this.query = query;
            this.thread = new Thread(new ThreadStart(this.Work));
            this.thread.Start();
        }

        private void Work()
        {
            this.busy = true;

            UDItem[] results = GetDefinitions(this.query);

            if (results.Length > 0)
            {
                for (int x = 0; x < results.Length; x++)
                {
                    if (x > 1)
                        break; // max 2 definitions per query!

                    String[] ud_split = results[x].definition.Split(new String[] { "\r\n" }, StringSplitOptions.None);

                    if (x > 0) UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket(""));
                    UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("10Urban Definition for: 14" + this.query));
                    UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket(""));

                    for (int i = 0; i < ud_split.Length; i++)
                    {
                        if (ud_split[i].Length > 1200) ud_split[i] = ud_split[i].Substring(0, 1200);
                        UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("06" + ud_split[i]));
                    }

                    ud_split = results[x].example.Split(new String[] { "\r\n" }, StringSplitOptions.None);
                    UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket(""));
                    UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("10Urban Example for: 14" + this.query));
                    UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket(""));

                    for (int i = 0; i < ud_split.Length; i++)
                    {
                        if (ud_split[i].Length > 1200) ud_split[i] = ud_split[i].Substring(0, 1200);
                        UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("03" + ud_split[i]));
                    }
                }
            }
            else
            {
                UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("Unable to find an urban definition for " + this.query + "!"));
            }

            this.busy = false;
        }

        private UDItem[] GetDefinitions(String _text)
        {
            List<UDItem> items = new List<UDItem>();

            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.urbandictionary.com/iphone/search/define?term=" + Uri.EscapeDataString(this.query));
                request.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30618)";
                WebResponse response = request.GetResponse();
                Stream stream = response.GetResponseStream();
                StreamReader reader = new StreamReader(stream);

                String text = reader.ReadToEnd();
                text = text.Replace("\\u0026", "\u0026");
                text = text.Replace("\\u003C", "\u003C");
                text = text.Replace("\\u003E", "\u003E");
                text = text.Replace("\\r", "\r\n");
                text = text.Replace("<br/>", "\r\n");
                text = RemoveHtml(text);

                UDItem current = new UDItem();

                while (text.Contains("\"definition\"") || text.Contains("\"example\""))
                {
                    int d_index = text.IndexOf("\"definition\":\"");
                    int e_index = text.IndexOf("\"example\":\"");

                    if ((e_index > -1 && e_index < d_index) || d_index == -1) // example
                    {
                        if (!String.IsNullOrEmpty(current.example))
                        {
                            items.Add(current);
                            current = new UDItem();
                        }

                        text = text.Substring(11 + e_index);
                        current.example = text.Substring(0, text.IndexOf("\""));

                        while (current.example.EndsWith("\r\n"))
                            current.example = current.example.Substring(0, current.example.Length - 2);

                        while (current.example.Contains("\r\n\r\n\r\n"))
                            current.example = current.example.Replace("\r\n\r\n\r\n", "\r\n\r\n");

                        current.example = RemoveEntities(current.example);
                        text = text.Substring(text.IndexOf("\""));
                    }
                    else if ((d_index > -1 && d_index < e_index) || e_index == -1) // definition
                    {
                        if (!String.IsNullOrEmpty(current.definition))
                        {
                            items.Add(current);
                            current = new UDItem();
                        }

                        text = text.Substring(14 + d_index);
                        current.definition = text.Substring(0, text.IndexOf("\""));

                        while (current.definition.EndsWith("\r\n"))
                            current.definition = current.definition.Substring(0, current.definition.Length - 2);

                        while (current.definition.Contains("\r\n\r\n\r\n"))
                            current.definition = current.definition.Replace("\r\n\r\n\r\n", "\r\n\r\n");

                        current.definition = RemoveEntities(current.definition);
                        text = text.Substring(text.IndexOf("\""));
                    }
                    else break;
                }

                if (!String.IsNullOrEmpty(current.example) || !String.IsNullOrEmpty(current.definition))
                    items.Add(current);

                reader.Close();
                stream.Flush();
                stream.Close();
                response.Close();
            }
            catch { }

            return items.ToArray();
        }

        private String RemoveHtml(String unfiltered)
        {
            String result = unfiltered;

            while (((result.IndexOf("<") > -1)
                && (result.IndexOf(">") > -1))
                && (result.IndexOf("<") < result.IndexOf(">")))
            {
                result = result.Substring(0, result.IndexOf("<"))
                    + result.Substring(result.IndexOf(">") + 1);
            }

            return result;
        }

        private String RemoveEntities(String str)
        {
            String _str = str;
            _str = _str.Replace("&quot;", "\"");
            _str = _str.Replace("&amp;", "&");
            _str = _str.Replace("&#160;", " ");
            _str = _str.Replace("&lt;", "<");
            _str = _str.Replace("&gt;", ">");
            return _str;
        }
    }

    class UDItem
    {
        public String definition = String.Empty;
        public String example = String.Empty;
    }
}
